using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using BanZuiCloudControlAgent.Core.QQ;
using BanZuiCloudControlAgent.Utils.Logging;

namespace BanZuiCloudControlAgent.Extensions.QQ
{
    /// <summary>
    /// QQ扩展功能实现，提供静态方法访问QQ功能
    /// </summary>
    public static class QQExtension
    {
        private static readonly Logger _logger = LogManager.GetLogger(nameof(QQExtension));

        #region QQ信息获取

        /// <summary>
        /// 获取所有在线QQ的信息
        /// </summary>
        /// <returns>QQ信息列表</returns>
        public static List<QQInfo> GetAllQQInfo()
        {
            try
            {
                _logger.Info("开始获取所有在线QQ信息");
                List<QQInfo> qqInfoList = new List<QQInfo>();

                // 获取QQ管理器实例
                QQManager qqManager = QQManager.GetInstance();

                // 获取所有在线QQ实例
                var onlineQQs = qqManager.GetOnlineQQs();
                _logger.Info($"找到 {onlineQQs.Count} 个在线QQ");

                foreach (var qq in onlineQQs)
                {
                    try
                    {
                        // 获取QQ号
                        string qqNumber = qq.QQNumber;
                        if (string.IsNullOrEmpty(qqNumber))
                        {
                            // 如果通过窗口标题无法获取QQ号，尝试通过QQTools获取
                            qqNumber = QQWrapper.GetQQNumber(qq.ProcessId);
                        }

                        if (string.IsNullOrEmpty(qqNumber))
                        {
                            _logger.Warn($"无法获取进程ID为 {qq.ProcessId} 的QQ号，跳过");
                            continue;
                        }

                        // 创建QQ信息对象
                        QQInfo qqInfo = new QQInfo
                        {
                            QQNumber = qqNumber,
                            ProcessId = qq.ProcessId,
                            IsOnline = true
                        };

                        // 获取昵称
                        qqInfo.Nickname = QQWrapper.GetNickname(qqNumber, qq.ProcessId);

                        // 获取ClientKey
                        qqInfo.ClientKey = QQWrapper.GetClientKey(qq.ProcessId);

                        // 获取HttpKey
                        qqInfo.HttpKey = QQWrapper.GetHttpKey(qq.ProcessId);

                        // 获取Cookie
                        qqInfo.Cookie = QQWrapper.GetCookie(qqNumber, qq.ProcessId);

                        // 获取QzoneCookie
                        qqInfo.QzoneCookie = QQWrapper.GetQzoneCookie(qqNumber, qq.ProcessId);

                        // 获取群列表
                        qqInfo.GroupList = QQWrapper.GetGroupList(qq.ProcessId);

                        qqInfoList.Add(qqInfo);
                        _logger.Info($"成功获取QQ {qqNumber} 的信息");
                    }
                    catch (Exception ex)
                    {
                        _logger.Error($"获取QQ信息时发生异常：{ex.Message}", ex);
                    }
                }

                _logger.Info($"成功获取 {qqInfoList.Count} 个QQ的信息");
                return qqInfoList;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取所有QQ信息时发生异常：{ex.Message}", ex);
                return new List<QQInfo>();
            }
        }

        /// <summary>
        /// 获取QQ信息，包括QQ号、在线状态等
        /// </summary>
        /// <param name="processId">QQ进程ID</param>
        /// <returns>QQ信息对象，如果无法获取则返回null</returns>
        public static QQInfo GetQQInfo(int processId)
        {
            try
            {
                // 使用QQManager获取QQ对象
                var qqManager = QQManager.GetInstance();
                var qq = qqManager.GetQQ(processId);
                
                if (qq == null)
                {
                    // 尝试使用QQWrapper获取QQ号
                    string qqNumber = QQWrapper.GetQQNumber(processId);
                    if (string.IsNullOrEmpty(qqNumber))
                    {
                        _logger.Error($"无法获取进程ID为 {processId} 的QQ号");
                        return null;
                    }
                    string nickname = QQWrapper.GetNickname(qqNumber, processId);
                    // 创建基本的QQ信息对象
                    return new QQInfo
                    {
                        QQNumber = qqNumber,
                        Nickname = nickname,
                        ProcessId = processId,
                        IsOnline = true,  // 能获取到QQ号通常说明已在线
                        GroupList = new List<string>(),
                        Cookie = GetCookie(qqNumber, processId)
                    };
                }
                
                // 从已获取的QQ对象构建信息
                var qqInfo = new QQInfo
                {
                    QQNumber = qq.QQNumber,
                    Nickname = qq.Nickname,
                    ProcessId = processId,
                    IsOnline = qq.IsOnline,
                    GroupList = new List<string>(),
                    Cookie = GetCookie(qq.QQNumber, processId)
                };

                return qqInfo;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ信息失败: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 获取指定QQ的群列表
        /// </summary>
        /// <param name="processId">QQ进程ID</param>
        /// <returns>群号列表，如果获取失败则返回空列表</returns>
        public static List<string> GetGroupList(int processId)
        {
            try
            {
                _logger.Info($"开始获取进程ID为 {processId} 的QQ群列表");

                // 获取QQ管理器实例
                QQManager qqManager = QQManager.GetInstance();

                // 获取QQ实例
                var qq = qqManager.GetQQ(processId);
                if (qq == null || !qq.IsOnline)
                {
                    _logger.Warn($"进程ID为 {processId} 的QQ不存在或不在线");
                    return new List<string>();
                }

                // 获取群列表
                var groupList = QQWrapper.GetGroupList(processId);

                _logger.Info($"成功获取进程ID为 {processId} 的QQ群列表，共 {groupList.Count} 个群");
                return groupList;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ群列表时发生异常：{ex.Message}", ex);
                return new List<string>();
            }
        }

        /// <summary>
        /// 获取指定QQ的Cookie
        /// </summary>
        /// <param name="qqNumber">QQ号</param>
        /// <param name="processId">QQ进程ID</param>
        /// <returns>Cookie字符串，如果无法获取则返回null</returns>
        public static string GetCookie(string qqNumber, int processId)
        {
            try
            {
                if (string.IsNullOrEmpty(qqNumber))
                {
                    _logger.Error("获取Cookie失败: QQ号为空");
                    return null;
                }

                // 调用QQWrapper获取Cookie
                string cookie = QQWrapper.GetCookie(qqNumber, processId);
                if (string.IsNullOrEmpty(cookie))
                {
                    _logger.Error($"获取QQ {qqNumber} 的Cookie失败");
                    return null;
                }

                return cookie;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ {qqNumber} 的Cookie时发生异常: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 直接获取指定QQ号和进程ID的QzoneCookie（不需要QQ实例）
        /// </summary>
        /// <param name="qqNumber">QQ号</param>
        /// <param name="processId">QQ进程ID</param>
        /// <returns>QzoneCookie，如果获取失败则返回null</returns>
        public static string GetQzoneCookie(string qqNumber, int processId)
        {
            try
            {
                _logger.Info($"开始直接获取QQ {qqNumber} 的QzoneCookie，进程ID: {processId}");

                if (string.IsNullOrEmpty(qqNumber) || processId <= 0)
                {
                    _logger.Error($"获取QzoneCookie参数错误，QQ号: {qqNumber}, 进程ID: {processId}");
                    return null;
                }

                // 获取QzoneCookie
                string qzoneCookie = QQWrapper.GetQzoneCookie(qqNumber, processId);

                if (string.IsNullOrEmpty(qzoneCookie))
                {
                    _logger.Warn($"无法获取QQ {qqNumber} 的QzoneCookie");
                    return null;
                }

                _logger.Info($"成功获取QQ {qqNumber} 的QzoneCookie");
                return qzoneCookie;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取QQ QzoneCookie时发生异常：{ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 从内存中判断指定QQ是否在线
        /// </summary>
        /// <param name="qqNumber">QQ号</param>
        /// <param name="processId">QQ进程ID</param>
        /// <returns>是否在线</returns>
        public static bool IsOnline(string qqNumber, int processId)
        {
            try
            {
                _logger.Info($"判断QQ {qqNumber} 是否在线，进程ID: {processId}");

                if (string.IsNullOrEmpty(qqNumber) || processId <= 0)
                {
                    _logger.Error($"判断QQ是否在线参数错误，QQ号: {qqNumber}, 进程ID: {processId}");
                    return false;
                }

                // 判断QQ是否在线
                bool isOnline = QQWrapper.IsOnline(qqNumber, processId);

                _logger.Info($"QQ {qqNumber} 在线状态: {isOnline}");
                return isOnline;
            }
            catch (Exception ex)
            {
                _logger.Error($"判断QQ是否在线时发生异常：{ex.Message}", ex);
                return false;
            }
        }

        #endregion

        #region QQ辅助方法
        /// <summary>
        /// 根据 Skey 和 Type 计算 Token。Type 为 1 时采用 MD5 计算，默认为 0 使用整数计算方式。
        /// </summary>
        /// <param name="Skey">输入的字符串，可以是 Skey 或 P_Skey</param>
        /// <param name="Type">类型标识，0 表示整数方式，1 表示 MD5 方式。默认值为0</param>
        /// <returns>计算后的 Token 字符串</returns>
        public static string GetGtkBySkey(string Skey, int Type = 0)
        {
            int salt = 5381;
            int len = Skey.Length;
            string token = string.Empty;

            if (Type == 1)
            {
                // 当 Type 为 1 时，使用 MD5 方式计算
                string md5Key = "tencentQQVIP123443safde&!%^%1282";
                // 初始 hash 为 salt 左移5位的结果转为文本
                string hash = (salt << 5).ToString();

                // 循环遍历 Skey 的每个字符（注意：易语言中通常是1开始，这里采用0基索引）
                for (int i = 0; i < len; i++)
                {
                    // 获取当前字符对应的 ASCII 代码
                    int asciiCode = (int)Skey[i];
                    // 将 salt 左移5位再加上 ASCII 代码的结果转文本后追加到 hash 字符串
                    hash += ((salt << 5) + asciiCode).ToString();
                    // 更新 salt 为当前字符的 ASCII 代码
                    salt = asciiCode;
                }

                // 在循环结束后，将预定义的 md5Key 拼接到 hash 后面
                hash += md5Key;
                // 计算 hash 字符串的 MD5 摘要
                token = GetMD5Hash(hash);
            }
            else
            {
                // 默认分支：使用整数运算计算 Token
                for (int i = 0; i < len; i++)
                {
                    // 每一步 salt = salt + (salt 左移5位) + 当前字符的 ASCII 代码
                    salt = salt + (salt << 5) + (int)Skey[i];
                }
                // 对 salt 和 2147483647 进行位与运算，并转换成字符串
                token = (salt & 2147483647).ToString();
            }

            return token;
        }

        /// <summary>
        /// 计算字符串的 MD5 摘要，并以16进制字符串返回
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>MD5 摘要的16进制字符串</returns>
        public static string GetMD5Hash(string input)
        {
            using (MD5 md5 = MD5.Create())
            {
                // 使用 UTF8 编码转换字符串为字节集
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                // 计算 MD5 哈希
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                // 将哈希字节转换为 16 进制字符串表示
                StringBuilder sb = new StringBuilder();
                foreach (var b in hashBytes)
                {
                    sb.Append(b.ToString("x2"));
                }
                return sb.ToString();
            }
        }

        /// <summary>
        /// 从Cookie字符串中根据指定的Key获取Value
        /// </summary>
        /// <param name="cookie">Cookie字符串</param>
        /// <param name="key">要查找的Key</param>
        /// <returns>Key对应的Value，如果未找到则返回null</returns>
        public static string GetValueFromCookie(string cookie, string key)
        {
            if (string.IsNullOrEmpty(cookie) || string.IsNullOrEmpty(key))
            {
                return null;
            }

            // 按分号分割Cookie字符串
            var parts = cookie.Split(';');
            foreach (var part in parts)
            {
                // 按等号分割每个部分
                var keyValue = part.Split('=');
                if (keyValue.Length == 2 && keyValue[0].Trim() == key)
                {
                    return keyValue[1].Trim();
                }
            }

            return null; // 未找到指定的Key
        }
        #endregion

    }

    /// <summary>
    /// QQ信息类，存储QQ的详细信息
    /// </summary>
    public class QQInfo
    {
        /// <summary>
        /// QQ号
        /// </summary>
        public string QQNumber { get; set; }

        /// <summary>
        /// QQ昵称
        /// </summary>
        public string Nickname { get; set; }

        /// <summary>
        /// QQ进程ID
        /// </summary>
        public int ProcessId { get; set; }

        /// <summary>
        /// 是否在线
        /// </summary>
        public bool IsOnline { get; set; }

        /// <summary>
        /// 客户端Key
        /// </summary>
        public string ClientKey { get; set; }

        /// <summary>
        /// HttpKey
        /// </summary>
        public string HttpKey { get; set; }

        /// <summary>
        /// Cookie
        /// </summary>
        public string Cookie { get; set; }

        /// <summary>
        /// QzoneCookie
        /// </summary>
        public string QzoneCookie { get; set; }

        /// <summary>
        /// 群列表
        /// </summary>
        public List<string> GroupList { get; set; } = new List<string>();

        /// <summary>
        /// 重写ToString方法
        /// </summary>
        public override string ToString()
        {
            return $"QQ号: {QQNumber}, 昵称: {Nickname}, 进程ID: {ProcessId}, 在线: {IsOnline}, 群数量: {GroupList.Count}";
        }
    }
}